﻿/*
 * eventmonitor.cpp
 *
 *  Created on: 2016年12月9日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_SCADA DM_API_EXPORT

#include <dm/scada/eventmonitor.hpp>
#include <dm/scada/scada.hpp>
#include <dm/scada/devicemgr.hpp>
#include <dm/scada/statusmgr.hpp>
#include <dm/scada/discretemgr.hpp>
#include <dm/scada/measuremgr.hpp>
#include <dm/scada/cumulantmgr.hpp>
#include <dm/scada/actionmgr.hpp>

#include <dm/datetime.hpp>

#include <iostream>

using namespace std;

namespace dm{
namespace scada{

CEventMonitor::CEventMonitor():CEventMgr(CEventMgr::ins()){
	m_p = m_q->getCurPos();
}

CEventMonitor::CEventMonitor( const ringpos_t* p ):CEventMgr(CEventMgr::ins()){
	m_p = *p;
}

CEventMonitor::~CEventMonitor(){
}

/**
 * 处理新事件.
 * 本函数只在run()模式下会被调用
 * @param pos 事件在队列中的位置
 * @param info 事件信息
 * @param overFlow 是否有事件丢失
 */
void CEventMonitor::onNew( const ringpos_t& pos,const CEvent& info,const bool& overFlow )const{
	dm::CDateTime dt = info.ts;
	cout <<pos.getCycle()<<"."<<pos.getPos()<<"["<<info.ts.seconds()<<'.'<<info.ts.mseconds()<<' '<<dt.toString().c_str()<<"]";
	if( overFlow )
		cout <<"(of)";
	switch( info.type ){
	case CEvent::Device:
	{
		CDeviceMgr& device = CDeviceMgr::ins();
		printf("设备 %s(id=%d,name=%s) 变为%d",device.desc(info.idx),device.id(info.idx),device.name(info.idx),info.value.device);
	}
		break;

	case CEvent::Status:
	{
		CStatusMgr& mgr = CStatusMgr::ins();
		printf("状态量 %s(id=%d,name=%s) 变为 %02X[%s]",mgr.desc(info.idx),mgr.id(info.idx),mgr.name(info.idx),info.value.status,mgr.valueDesc(info.idx,info.value.status));
	}
		break;

	case CEvent::Discrete:
	{
		CDiscreteMgr& mgr = CDiscreteMgr::ins();
		printf("离散量 %s(id=%d,name=%s) 变为 %d[%s]",mgr.desc(info.idx),mgr.id(info.idx),mgr.name(info.idx),info.value.discrete,mgr.valueDesc(info.idx,info.value.discrete));
	}
		break;

	case CEvent::Action:
	{
		CActionMgr& mgr = CActionMgr::ins();
		printf("动作 %s(id=%d,name=%s) 变为 %02X[%s]",mgr.desc(info.idx),mgr.id(info.idx),mgr.name(info.idx),info.value.action,mgr.valueDesc(info.idx,info.value.action));
	}
		break;

	case CEvent::MeasureAlarm:
	{
		CMeasureMgr& mgr = CMeasureMgr::ins();
		printf("测量量 %s(id=%d,name=%s) 告警变为 %02X",mgr.desc(info.idx),mgr.id(info.idx),mgr.name(info.idx),info.value.measure);
	}
		break;

	case CEvent::CumulantAlarm:
	{
		CCumulantMgr& mgr = CCumulantMgr::ins();
		printf("累计量 %s(id=%d,name=%s) 告警变为 %02X",mgr.desc(info.idx),mgr.id(info.idx),mgr.name(info.idx),info.value.cumulant);
	}
		break;
	default:
		cout <<"未知类型 索引为"<<info.idx<<" "<<info.value.all;
	}

	cout <<endl;
}

/**
 * 事件过滤函数
 * 对于用户使用时，可以重载本函数，对新事件的信息进行过滤。
 * 如果不希望在onNew()函数中处理，可以返回true过滤掉。
 * 本函数只在run()模式下会被调用
 * @param
 * @param
 * @param
 * @return 是否过滤
 * - true 过滤掉该事件
 * - false 不过滤该事件
 */
bool CEventMonitor::filter( const ringpos_t& /*pos*/,const CEvent& /*info*/,const bool& /*overflow*/ )const{
	return false;
}

/**
 * 事件监视器运行接口。
 * 本函数适合在执行线程中被调用。比如main函数。
 * 调用后，将占用该线程，直到程序退出。
 * 当有新的事件到后，会自动执行filter()对事件进行过滤，然后执行onNew()函数。
 */
void CEventMonitor::run(){
	CEvent info;
	bool overflow;

	while( true ){
		if(m_q->waitAndCheckOver(m_p,overflow,info,1))
			continue;
		if( !filter(m_p,info,overflow) )
			onNew(m_p,info,overflow);
		if( overflow )
			m_p = m_q->getCurPos();
	}
}

/**
 * 尝试获取事件
 * @param info 事件信息
 * @param overflow 是否有溢出
 * @return 是否有新事件
 */
bool CEventMonitor::tryGet( CEvent& info,bool& overflow ){
	return m_q->popAndCheckOver( m_p,overflow,info);
}

/**
 * 获取事件
 * 本函数会阻塞执行线程
 * @param info 事件信息
 * @param overflow 是否有溢出
 */
void CEventMonitor::get( CEvent& info,bool& overflow ){
	m_q->waitAndCheckOver( m_p,overflow,info);
}

}
}


